﻿'// ========================================================================= '
'// ------------------------------------------------------------------------- '
'//!				\file		CM_Dims.vb
'			        \date		june 2010
'			        \author		TNick
'
'			        \brief		
'
'
'   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'   This file is considered universal knowledge. No restrictions
'   are imposed; use as you see fit.
'   Please read ReadMe.txt and Licence.txt in root folder
'   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'
'   http://docs.autodesk.com/ACD/2011/ESP/filesMDG/WS73099cc142f48755-5c83e7b1120018de8c0-20a1.htm
'
'// ------------------------------------------------------------------------- '
'// ========================================================================= '
'//
'//
'//
'//
'//  IMPORTS     ------------------------------------------------------------ '
#Region "Imports"

Imports System
Imports Microsoft.Win32

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Customization
'Imports Autodesk.AutoCAD.Colors
'Imports Autodesk.AutoCAD.GraphicsSystem

#End Region
'//  IMPORTS     ============================================================ '
'//
'//
'//
'//
'//  DEFINITIONS    --------------------------------------------------------- '
<Assembly: CommandClass(GetType(CM_Dims))> 


#Region "Public Structures"

'// --------------------------------------------------------------------- '
'// describes a saves style

Public Structure DIMSTY

    '// name of this style
    Dim sName As String

    '// name of autocad style
    Dim sAcName As String

    '// text height on this style
    Dim dTxSz As Double

    '// arrow head size
    Dim dHdSz As Double

    '// vertical position
    Dim dTxVerPos As Double

    '// prefix and suffix
    Dim sPreSuf As string

    '// gap 'till text
    Dim dTxGap As Double

    '// extension line offset
    Dim dExO1 As Double
    Dim dExO2 As Double
    '// size of dimension line
    Dim dASz As Double


    '// various flags
    Dim lFlgs As Long
    '// small values
    Dim byVerPos As byte
    Dim byHorPos As byte
    Dim byUnit As byte
    Dim byPrec As byte
    Dim byFit As byte

End Structure
'// ===================================================================== '


'// --------------------------------------------------------------------- '
'// defines the settings for this module
Public Structure DIMSTG

    '// ratio
    Dim dDimScale As Double
    '// current style
    Dim iCrtSty As Integer

End Structure
'// ===================================================================== '



#End Region


'//  DEFINITIONS    ========================================================= '
'//
'//
'//
'//
'//  DATA    ---------------------------------------------------------------- '


'//  DATA    ================================================================ '
'//
'//
'//
'//
'//  CLASS    --------------------------------------------------------------- '
Public Class CM_Dims
    Inherits CModule


    '// --------------------------------------------------------------------- '
    '// DATA

#Region "Public Constants"
    '// name as displayed in various places
    Public Const sAPPNAME As String = "Dimensions"
    '// version as displayed in various places
    Public Const sAPPVER As String = "1.0.0.0"
    '// short description
    Public sAPPTIP As String

    '// Command. Brings up the settings dialog
    Public Const sCMD_SETTINGS As String = "TNIK_DIM_STG"
    '// Command. Place dimensions on polyline
    Public Const sCMD_ONPOLY As String = "TNIK_DIM_PLY"

    Public const FLG_DIMTOH As Long = &H1
    Public const FLG_DIMTOFL As Long = &H2
    Public const FLG_DIMTMOVE_1 As Long = &H4
    Public const FLG_DIMTMOVE_2 As Long = &H8
    Public const FLG_DIMTIX As Long = &H10
    Public const FLG_DIMTIH As Long = &H20
    Public const FLG_DIMSOXD As Long = &H40
    Public const FLG_DIMSE1 As Long = &H80
    Public const FLG_DIMSE2 As Long = &H100
    Public const FLG_DIMSD1 As Long = &H200
    Public const FLG_DIMSD2 As Long = &H400
    Public const FLG_DIMSAH As Long = &H800

#End Region

    '// this is where the settings are stored durring run-time
    Public Shared Stgs As DIMSTG
    '// list of saved styles
    Public Shared SavedSty() As DIMSTY

    '// ===================================================================== '

    Private Const TXSEPSTY As String = "<^>"

    '// --------------------------------------------------------------------- '
    '// This function saves a structure to a string
    Public Shared Function DimStyToText(ByRef sSty As DIMSTY) As String

        Dim sOut As String = ""

        sOut = _
            sSty.sName & TXSEPSTY & _
            sSty.sAcName & TXSEPSTY & _
            sSty.dTxSz.ToString() & TXSEPSTY & _
            sSty.dHdSz.ToString() & TXSEPSTY & _
            sSty.dTxVerPos.ToString() & TXSEPSTY & _
            sSty.sPreSuf.ToString() & TXSEPSTY & _
            sSty.dTxGap.ToString() & TXSEPSTY & _
            sSty.dExO1.ToString() & TXSEPSTY & _
            sSty.dExO2.ToString() & TXSEPSTY & _
            sSty.dASz.ToString() & TXSEPSTY & _
            sSty.lFlgs.ToString() & _
            sSty.byVerPos.ToString() & TXSEPSTY & _
            sSty.byHorPos.ToString() & TXSEPSTY & _
            sSty.byUnit.ToString() & TXSEPSTY & _
            sSty.byPrec.ToString() & TXSEPSTY & _
            sSty.byFit.ToString() & TXSEPSTY

        Return sOut
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// This function loads a structure from a string
    Public Shared Function DimStyFromText( _
        ByRef sStrIn As String, _
        ByRef sSty As DIMSTY) As Boolean

        Dim sInterm() As String
        Dim sSplit(0 To 0) As String
        sSplit(0) = TXSEPSTY
        Try
            sInterm = sStrIn.Split(sSplit, StringSplitOptions.None)
            sSty.sName = sInterm(0)
            sSty.sAcName = sInterm(1)
            sSty.dTxSz = CDbl(sInterm(2))
            sSty.dHdSz = CDbl(sInterm(3))

            sSty.dTxVerPos = CDbl(sInterm(4))
            sSty.sPreSuf = sInterm(5)
            sSty.dTxGap = CDbl(sInterm(6))
            sSty.dExO1 = CDbl(sInterm(7))
            sSty.dExO2 = CDbl(sInterm(8))
            sSty.dASz = CDbl(sInterm(9))

            sSty.lFlgs = CLng(sInterm(10))

            sSty.byVerPos = CByte(sInterm(11))
            sSty.byHorPos = CByte(sInterm(12))
            sSty.byUnit = CByte(sInterm(13))
            sSty.byPrec = CByte(sInterm(14))
            sSty.byFit = CByte(sInterm(15))

        Catch ex As System.Exception
            Return False
        End Try
        Return True
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// The function removes a style from the list
    Public Shared Sub DimStyRem(ByRef sAry() As DIMSTY, ByVal iIdx As Integer)
        If (sAry Is Nothing) Then
            Return
        End If
        If (iIdx >= sAry.Length) Then
            Return
        End If

        If (iIdx = sAry.Length - 1) Then
            '// no shift required
            If (iIdx = 0) Then
                '// this was the only one
                sAry = Nothing
            Else
                ReDim Preserve sAry(0 To sAry.Length - 2)
            End If
        Else
            '// we need to shift
            For i As Integer = iIdx To sAry.Length - 2
                sAry(i) = sAry(i + 1)
            Next
            ReDim Preserve sAry(0 To sAry.Length - 2)
        End If
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// The function adds a style to the list
    Public Shared Sub DimStyAdd(ByRef sAry() As DIMSTY, ByRef sNew As DIMSTY)
        If (sAry Is Nothing) Then
            ReDim sAry(0 To 0)
        Else
            ReDim Preserve sAry(0 To sAry.Length)
        End If
        sAry(sAry.Length - 1) = sNew
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// The function extracts data from an existing style
    Public Shared Function DimStyFromSty( _
        ByRef acDoc As Document, _
        ByRef sStyName As String, _
        ByRef sOut As DIMSTY, _
        ByRef sErrStr As String) _
        As Boolean

        Dim bRet As Boolean = False

        Using acTrans As Transaction = _
            acDoc.Database.TransactionManager.StartTransaction()
            Try
                '// get dimension style table and make shure we have this style
                Dim acDimStyTbl As DimStyleTable = DirectCast( _
                        acTrans.GetObject(acDoc.Database.DimStyleTableId, _
                                          OpenMode.ForRead),  _
                        DimStyleTable)
                If (acDimStyTbl.Has(sStyName) = False) Then
                    sErrStr = CMain._T(TX.TABLES)
                    Exit Try
                End If

                '// open the style to be able to read it's properties
                Dim acDimSty As DimStyleTableRecord = DirectCast( _
                        acTrans.GetObject(acDimStyTbl(sStyName), _
                                          OpenMode.ForRead),  _
                        DimStyleTableRecord)

                sOut.lFlgs = 0
                sOut.sName = acDimSty.Name
                sOut.sAcName = acDimSty.Name
                sOut.dTxSz = acDimSty.Dimtxt
                sOut.dHdSz = acDimSty.Dimasz

                sOut.dTxVerPos = acDimSty.Dimtvp 
                If acDimSty.Dimtoh <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTOH
                End If
                If acDimSty.Dimtofl <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTOFL
                End If
                If acDimSty.Dimtmove  = 1 then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTMOVE_1
                elseIf acDimSty.Dimtmove  = 2 then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTMOVE_2
                End If
                If acDimSty.Dimtix <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTIX
                End If
                If acDimSty.Dimtih <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTIH 
                End If
                If acDimSty.Dimsoxd <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSOXD 
                End If
                If acDimSty.Dimse1 <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSE1 
                End If
                If acDimSty.Dimse2 <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSE2 
                End If
                If acDimSty.Dimsd1 <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSD1 
                End If
                If acDimSty.Dimsd2 <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSD2 
                End If
                If acDimSty.Dimsah <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSAH
                End If
                sOut.sPreSuf = acDimSty.Dimpost
                sOut.byVerPos =acDimSty.Dimtad
                sOut.byHorPos =acDimSty.Dimjust
                sOut.byUnit = acDimSty.Dimlunit
                sOut.dTxGap = acDimSty.Dimgap
                sOut.dExO1 = acDimSty.Dimexo
                sOut.dExO2 = acDimSty.Dimexe
                sOut.byPrec = acDimSty.Dimdec
                sOut.byFit = acDimSty.Dimatfit
                sOut.dASz = acDimSty.Dimasz

                bRet = True
                acTrans.Commit()
            Catch ex As System.Exception
                acTrans.Abort()
                CMain.DebugException(ex)
                CMain.PopUpExc()
            End Try
            GC.Collect()
            GC.WaitForPendingFinalizers()
        End Using

        Return bRet
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// The function extracts data from an existing style
    Public Shared Function DimStyFromDim( _
        ByRef acDoc As Document, _
        ByRef sOut As DIMSTY, _
        ByRef sErrStr As String) _
        As Boolean

        Dim bRet As Boolean = False
        Dim acAlDim As AlignedDimension

        Using acTrans As Transaction = _
            acDoc.Database.TransactionManager.StartTransaction()
            Try

                Dim peo As PromptEntityOptions
                peo = New PromptEntityOptions(vbLf & _
                                CMain._T(TX.SELDIMALGN) & ": " & vbNewLine)
                peo.SetRejectMessage(vbLf & CMain._T(TX.ERR_OBJTY) & "!")
                peo.AddAllowedClass(GetType(Autodesk.AutoCAD. _
                    DatabaseServices.AlignedDimension), False)
                Dim per As PromptEntityResult = acDoc.Editor.GetEntity(peo)
                If per.Status <> PromptStatus.OK Then Return False
                acAlDim = DirectCast( _
                    acTrans.GetObject(per.ObjectId, OpenMode.ForRead),  _
                          AlignedDimension)

                ''// open the style to be able to read it's properties
                Dim acDimSty As DimStyleTableRecord = DirectCast( _
                    acTrans.GetObject(acAlDim.DimensionStyle, OpenMode.ForRead),  _
                    DimStyleTableRecord)
                sOut.lFlgs = 0
                If (String.IsNullOrEmpty(acDimSty.Name)) Then
                    sOut.sName = "New style"
                    sOut.sAcName = "Standard"
                Else
                    sOut.sName = acDimSty.Name
                    sOut.sAcName = acDimSty.Name
                End If
                sOut.dTxSz = acAlDim.Dimtxt
                sOut.dHdSz = acAlDim.Dimasz
                sOut.dTxVerPos = acAlDim.Dimtvp 
                If acAlDim.Dimtoh <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTOH
                End If
                If acAlDim.Dimtofl <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTOFL
                End If
                If acAlDim.Dimtmove  = 1 then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTMOVE_1
                elseIf acAlDim.Dimtmove  = 2 then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTMOVE_2
                End If
                If acAlDim.Dimtix <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTIX
                End If
                If acAlDim.Dimtih <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMTIH 
                End If
                If acAlDim.Dimsoxd <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSOXD 
                End If
                If acAlDim.Dimse1 <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSE1 
                End If
                If acAlDim.Dimse2 <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSE2 
                End If
                If acAlDim.Dimsd1 <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSD1 
                End If
                If acAlDim.Dimsd2 <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSD2 
                End If
                If acAlDim.Dimsah <> False then
                    sOut.lFlgs = sOut.lFlgs or FLG_DIMSAH
                End If
                sOut.sPreSuf = acAlDim.Dimpost
                sOut.byVerPos =acAlDim.Dimtad
                sOut.byHorPos =acAlDim.Dimjust
                sOut.byUnit = acAlDim.Dimlunit
                sOut.dTxGap = acAlDim.Dimgap
                sOut.dExO1 = acAlDim.Dimexo
                sOut.dExO2 = acAlDim.Dimexe
                sOut.byPrec = acAlDim.Dimdec
                sOut.byFit = acAlDim.Dimatfit
                sOut.dASz = acAlDim.Dimasz


                bRet = True
                acTrans.Commit()
            Catch ex As System.Exception
                acTrans.Abort()
                CMain.DebugException(ex)
                CMain.PopUpExc()
            End Try
            GC.Collect()
            GC.WaitForPendingFinalizers()
        End Using

        Return bRet
    End Function
    '// ===================================================================== '

    '// Tells if a style with specified name is present or not
    Public Shared Function DimStyHas( _
        ByRef sAry() As DIMSTY, _
        ByVal sSrc As String, _
        ByRef iIdx As Integer) _
        As Boolean

        If (sAry Is Nothing) Then
            Return False
        End If

        sSrc = sSrc.ToUpper()
        For i As Integer = 0 To sAry.Length - 1
            If sSrc = sAry(i).sName.ToUpper Then
                iIdx = i
                Return True
            End If
        Next
        Return False
    End Function
    '// ===================================================================== '


#Region "Private general purpose functions"


    '// --------------------------------------------------------------------- '
    '// This function saves current settings
    Private Shared Sub SaveSett()
        CSett.SaveStg(sAPPNAME, "Stgs.dDimScale", Stgs.dDimScale)
        CSett.SaveStg(sAPPNAME, "Stgs.iCrtSty", Stgs.iCrtSty)
        If (SavedSty IsNot Nothing) Then
            For i As Integer = 0 To SavedSty.Length - 1
                CSett.SaveStg(sAPPNAME, "Stgs.SavedStyle_" & i.ToString, _
                              DimStyToText(SavedSty(i)))
            Next i
            CSett.SaveStg(sAPPNAME, "Stgs.SavedStyle_" & _
                          SavedSty.Length.ToString, _
                          "")
        Else
            CSett.SaveStg(sAPPNAME, "Stgs.SavedStyle_0", "")
        End If
    End Sub
    '// ===================================================================== '


    '// --------------------------------------------------------------------- '
    '// This function loads current settings
    Private Shared Sub GetSett()
        Stgs.dDimScale = CSett.GetDblStg(sAPPNAME, "Stgs.dDimScale", 1)
        Stgs.iCrtSty = CSett.GetIntStg(sAPPNAME, "Stgs.iCrtSty", 0)

        Dim sSetSty As String
        Dim sSty As DIMSTY = Nothing
        For i As Integer = 0 To Integer.MaxValue - 1
            sSetSty = CSett.GetStrStg(sAPPNAME, "Stgs.SavedStyle_" & i.ToString, "")
            If (String.IsNullOrEmpty(sSetSty)) Then
                Exit For
            End If
            If (DimStyFromText(sSetSty, sSty) = True) Then
                If (SavedSty Is Nothing) Then
                    ReDim SavedSty(0 To 0)
                Else
                    ReDim Preserve SavedSty(0 To SavedSty.Length)
                End If
                SavedSty(SavedSty.Length - 1) = sSty
            Else
                Debug.Print("Reg saved style not understood: <" & sSetSty & ">")
            End If
        Next
    End Sub
    '// ===================================================================== '


    '// --------------------------------------------------------------------- '
    '// This function shows current settings
    Private Shared Function PrintStg(ByRef lcStg As DIMSTG) As String
        Return (vbCrLf & CMain._T(TX.CSTG) & ": " & sAPPNAME & vbCrLf & _
          CMain._T(TX.IMDB_DIMSCL) & " = " & CStr(lcStg.dDimScale) & vbCrLf)
        Return Nothing
    End Function
    '// ===================================================================== '


#End Region


#Region "Common interface" ' -----------------------

    '// --------------------------------------------------------------------- '
    '// a new instance is created
    Public Sub New()
        Try
            sAPPTIP = CMain._T(TX.DIM_INFO)
            Return
        Catch ex As System.Exception
            CMain.DebugException(ex)
            Return
        End Try
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// the module is asked to terminate
    Public Overrides Function Terminate() As Boolean
        Try
            SaveSett()
            Return True
        Catch ex As System.Exception
            CMain.DebugException(ex)
            Return False
        End Try
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// the module is asked to tell it's name
    Public Shared Function GetName() As String
        Return sAPPNAME
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// the module is asked to tell about itself
    Public Shared Sub GetInfos(ByRef sName As String, ByRef sVer As String, ByRef sTip As String)
        sName = sAPPNAME
        sVer = sAPPVER
        sTip = CMain._T(TX.DIM_INFO)
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// the module is asked to tell about itself
    Public Shared Function GetDescription() As String
        Dim sOut As String = sAPPNAME
        Try
            Dim cIni As New IniWork(CApp.sAppPath & CMain.APPSTG)
            If cIni.HasErrors = True Then Exit Try
            sOut = cIni.Read(sAPPNAME, CMain.DESCRKEY & _
                             CMain.eAppLang.ToString, sAPPNAME)
        Catch ex As System.Exception
            CMain.DebugException(ex)
        End Try
        Return sOut
    End Function
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// the module is informed about application start-up
    Public Shared Sub DoPrereq()
        Try
            ' this function is called at application start-up in order to 
            ' allow applications to do any prerequisites
            ' there is no instance of this class at this time
            GetSett()
        Catch ex As System.Exception
            CMain.DebugException(ex)
        End Try
        Return
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// create the user interface for this module
    Public Shared Sub DoCUI( _
     ByRef pcs As CustomizationSection, _
     ByRef mg As MacroGroup)
        ' this function is called when a CUI is builded in order to
        ' allow any application specifics
        Try
#If HARDCORE_CUI Then
            If CApp.cuiCl Is Nothing Then Exit Try
            CApp.cuiCl.AddMacro(sCMD_ONPOLY, "DIM_Poly")
            CApp.cuiCl.AddMacro(sCMD_SETTINGS, "DIM_Settings")

            CApp.cuiCl.AddToolbar( _
                sAPPNAME, _
                Application.MainWindow.Location.X, _
                100 + MIDS.FSK_PT3D * 30)
            CApp.cuiCl.AddToolbarBtn(CMain._T(TX.DIMONPOLY), sCMD_ONPOLY)
            CApp.cuiCl.AddToolbarBtn(CMain._T(TX.SETTINGS), sCMD_SETTINGS)

#Else

			Dim mm1 As MenuMacro = Nothing
			mm1 = New MenuMacro(mg, sCMD_ONPOLY, "^C^C" & sCMD_ONPOLY, "ID_" & sCMD_ONPOLY)
			mm1 = New MenuMacro(mg, sCMD_SETTINGS, "^C^C" & sCMD_SETTINGS, "ID_" & sCMD_SETTINGS)


			Dim tbBtn As ToolbarButton = Nothing
			Dim newTb As Toolbar = New Toolbar(sAPPNAME, pcs.MenuGroup)
			newTb.ElementID = "EID_TNIK_Dims"
			newTb.ToolbarOrient = ToolbarOrient.floating
			newTb.ToolbarVisible = ToolbarVisible.show


			tbBtn = New ToolbarButton(newTb, -1)
			tbBtn.Name = CMain._T(tx.ONPOLY)
			tbBtn.MacroID = "ID_" & sCMD_ONPOLY

			tbBtn = New ToolbarButton(newTb, -1) ' separator

			tbBtn = New ToolbarButton(newTb, -1)
			tbBtn.Name = CMain._T(tx.SETTINGS)
			tbBtn.MacroID = "ID_" & sCMD_SETTINGS
#End If

        Catch ex As System.Exception
            CMain.DebugException(ex)
        End Try
    End Sub
    '// ===================================================================== '


#End Region

#Region "Internal base work"


#End Region


#Region "C O M M A N D S"


    '// --------------------------------------------------------------------- '
    '// display settings dialog
    <CommandMethod(sCMD_SETTINGS)> _
    Public Sub Show_Settings()
        Try
            Dim StgD As CST_Dims = New CST_Dims
            Application.ShowModelessDialog(StgD)
        Catch ex As System.Exception
            CMain.PopUpExc()
            CMain.DebugException(ex)
        End Try
        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Sub
    '// ===================================================================== '

    '// --------------------------------------------------------------------- '
    '// Place dimensions on polylines
    <CommandMethod(sCMD_ONPOLY, CommandFlags.UsePickSet)> _
    Public Sub DimOnPoly()
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        If (acDoc Is Nothing) Then Return

        Dim i As Integer
        Dim acPt As Point2d
        Dim lnIn As FSK_LINE
        Dim TheObj As DBObject
        Dim lary As LnMg
        Dim acPoly As Polyline = Nothing
        Dim db As Database = acDoc.Database
        Dim ed As Editor = acDoc.Editor
        lary.iAlc = 128
        lary.iUsd = 0
        ReDim lary.ln(0 To lary.iAlc - 1)


        Using acTrans As Transaction = _
            db.TransactionManager.StartTransaction()
            Try
                Dim acBlkTblRec As BlockTableRecord = DirectCast( _
                        acTrans.GetObject(db.CurrentSpaceId, _
                                            OpenMode.ForWrite),  _
                        BlockTableRecord)
                Dim acSSPrompt As PromptSelectionResult = acDoc.Editor.SelectImplied()

                Dim acSSet As SelectionSet = Nothing
                If acSSPrompt.Status = PromptStatus.OK Then
                    acSSet = acSSPrompt.Value
                Else
                    Dim pso As New PromptSelectionOptions()
                    Dim acTypValAr(0) As TypedValue
                    acTypValAr.SetValue(New TypedValue(DxfCode.Start, "LWPOLYLINE"), 0)
                    Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr)
                    ' Add our keywords
                    pso.MessageForAdding = vbLf & CMain._T(TX.ADDOBJTOSEL)
                    pso.MessageForRemoval = vbLf & CMain._T(TX.REMOBJTOSEL)
                    Dim psr As PromptSelectionResult = ed.GetSelection(pso, acSelFtr)

                    If psr.Status <> PromptStatus.OK Then
                        Exit Try
                    End If
                    acSSet = psr.Value
                End If
                For Each sobj As SelectedObject In acSSet
                    TheObj = acTrans.GetObject(sobj.ObjectId, OpenMode.ForRead)
                    If (TypeOf TheObj Is Polyline) Then
                        acPoly = DirectCast(TheObj, Polyline)
                        acPt = acPoly.GetPoint2dAt(0)
                        lnIn.E_1 = acPt.X
                        lnIn.N_1 = acPt.Y
                        For i = 1 To acPoly.NumberOfVertices - 1
                            acPt = acPoly.GetPoint2dAt(i)
                            lnIn.E_2 = acPt.X
                            lnIn.N_2 = acPt.Y

                            Dim dDst As Double = (lnIn.E_2 - lnIn.E_1)
                            If (Math.Abs(dDst) < CMain.MARGIN) Then
                                If (Math.Abs(lnIn.E_2 - lnIn.E_1) < CMain.MARGIN) Then
                                    Continue For
                                End If
                                lnIn.bVert = True
                                lnIn.m = 0
                                lnIn.b = 0
                            Else
                                lnIn.bVert = False
                                lnIn.m = ((lnIn.N_2 - lnIn.N_1) / dDst)
                                lnIn.b = lnIn.N_1 - lnIn.m * lnIn.E_1
                            End If
                            If (CMain.IsLnInChain(lary, lnIn) = Integer.MaxValue) Then
                                CMain.AddLnToChain(lary, lnIn)
                            End If
                            lnIn.E_1 = lnIn.E_2
                            lnIn.N_1 = lnIn.N_2
                        Next
                        If acPoly.Closed = True Then
                            acPoly = DirectCast(TheObj, Polyline)
                            acPt = acPoly.GetPoint2dAt(0)
                            lnIn.E_2 = acPt.X
                            lnIn.N_2 = acPt.Y
                            Dim dDst As Double = (lnIn.E_2 - lnIn.E_1)
                            If (Math.Abs(dDst) < CMain.MARGIN) Then
                                If (Math.Abs(lnIn.E_2 - lnIn.E_1) < CMain.MARGIN) Then
                                    GoTo Closed_Finish
                                End If
                                lnIn.bVert = True
                                lnIn.m = 0
                                lnIn.b = 0
                            Else
                                lnIn.bVert = False
                                lnIn.m = ((lnIn.N_2 - lnIn.N_1) / dDst)
                                lnIn.b = lnIn.N_1 - lnIn.m * lnIn.E_1
                            End If
                            If (CMain.IsLnInChain(lary, lnIn) = Integer.MaxValue) Then
                                CMain.AddLnToChain(lary, lnIn)
                            End If
                        End If
Closed_Finish:
                    End If
                Next
                '// we now have a collection of lines that have to be dimensioned

                Dim acADim As AlignedDimension

                Dim dTxtH As Double
                Dim dArvH As Double
                Dim iSt As Integer = Stgs.iCrtSty
                If (SavedSty Is Nothing) Then
                    dTxtH = Stgs.dDimScale
                    dArvH = Stgs.dDimScale
                Else
                    If (iSt > SavedSty.Length - 1) Then iSt = 0
                    dTxtH = Stgs.dDimScale * SavedSty(iSt).dTxSz
                    dArvH = Stgs.dDimScale * SavedSty(iSt).dTxSz
                End If
                If (dTxtH < CMain.MARGIN) Then
                    dTxtH = 1
                End If
                For i = 0 To lary.iUsd - 1
                    '// http://www.caddmanager.com/CMB/2009/09/cad-standards-autocad-dimension-variables/

                    acADim = New AlignedDimension()
                    acADim.SetDatabaseDefaults()
                    acADim.XLine1Point = New Point3d( _
                        lary.ln(i).E_1, lary.ln(i).N_1, 0)
                    acADim.XLine2Point = New Point3d( _
                        lary.ln(i).E_2, lary.ln(i).N_2, 0)
                    acADim.DimLinePoint = acADim.XLine1Point
                    acADim.DimensionStyle = db.Dimstyle
                    acADim.Dimtxt = dTxtH '// text height
                    acADim.Dimasz = dArvH

                    If (SavedSty Isnot Nothing) Then

                        acADim.Dimtvp  = SavedSty(iSt).dTxVerPos
                        If (SavedSty(iSt).lFlgs and FLG_DIMTOH) <> 0 then
                            acADim.Dimtoh = True
                        Else
                            acADim.Dimtoh = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMTOFL) <> 0 then
                            acADim.Dimtofl = True
                        Else
                            acADim.Dimtofl = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMTMOVE_1) <> 0 then
                            acADim.Dimtmove = True
                        Else
                            acADim.Dimtmove = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMTMOVE_1) <> 0 then
                            acADim.Dimtmove = 1
                        ElseIf (SavedSty(iSt).lFlgs and FLG_DIMTMOVE_2) <> 0 then
                            acADim.Dimtmove = 2
                        Else
                            acADim.Dimtmove = 0
                        End If

                        If (SavedSty(iSt).lFlgs and FLG_DIMTIX) <> 0 then
                            acADim.Dimtix = True
                        Else
                            acADim.Dimtix = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMTIH) <> 0 then
                            acADim.Dimtih = True
                        Else
                            acADim.Dimtih = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMSOXD) <> 0 then
                            acADim.Dimsoxd = True
                        Else
                            acADim.Dimsoxd = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMSE1) <> 0 then
                            acADim.Dimse1 = True
                        Else
                            acADim.Dimse1 = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMSE2) <> 0 then
                            acADim.Dimse2 = True
                        Else
                            acADim.Dimse2 = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMSD1) <> 0 then
                            acADim.Dimsd1 = True
                        Else
                            acADim.Dimsd1 = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMSD2) <> 0 then
                            acADim.Dimsd2 = True
                        Else
                            acADim.Dimsd2 = False
                        End If
                        If (SavedSty(iSt).lFlgs and FLG_DIMSAH) <> 0 then
                            acADim.Dimsah = True
                        Else
                            acADim.Dimsah = False
                        End If

                        acADim.Dimpost = SavedSty(iSt).sPreSuf
                        acADim.Dimtad = SavedSty(iSt).byVerPos
                        acADim.Dimjust = SavedSty(iSt).byHorPos 
                        acADim.Dimlunit = SavedSty(iSt).byUnit
                        acADim.Dimgap = SavedSty(iSt).dTxGap
                        acADim.Dimexo = SavedSty(iSt).dExO1
                        acADim.Dimexe = SavedSty(iSt).dExO2
                        acADim.Dimdec = SavedSty(iSt).byPrec
                        acADim.Dimatfit = SavedSty(iSt).byFit
                        acADim.Dimasz = SavedSty(iSt).dASz

                    End If


                    '' Add the new object to Model space and the transaction
                    acBlkTblRec.AppendEntity(acADim)
                    acTrans.AddNewlyCreatedDBObject(acADim, True)
                    acADim = Nothing
                Next i
                acTrans.Commit()
            Catch ex As System.Exception
                acTrans.Abort()
                CMain.DebugException(ex)
                CMain.PopUpExc()
            End Try
            GC.Collect()
            GC.WaitForPendingFinalizers()
        End Using
    End Sub
    '// ===================================================================== '

#End Region



End Class
'//  CLASS    =============================================================== '
'//
'//
'//
'//
'//  FUNCTIONS    ----------------------------------------------------------- '

'//  FUNCTIONS    =========================================================== '
'//
'//
'//
'//
'// ------------------------------------------------------------------------- '
'// ========================================================================= '





                    ' '' ''acADim.Dimsd1 = False '// supress dimension line
                    ' '' ''acADim.Dimsd2 = False '// supress dimension line

                    ' '' ''DIMATFIT (2000) – Determines how dimension text and arrows 
                    ' '' '' are arranged when space is not sufficient to place 
                    ' '' '' both within the extension lines.
                    ' '' ''0 Places both text and arrows outside extension lines
                    ' '' ''1 Moves arrows first, then text
                    ' '' ''2 Moves text first, then arrows
                    ' '' ''3 Moves either text or arrows, whichever fits best
                    ' '' ''A leader is added to moved dimension text when DIMTMOVE is set to 1.
                    ' '' ''acADim.Dimatfit = 2

                    ' '' ''DIMSAH (R12) – Controls the display of dimension line arrowhead blocks.
                    ' '' ''Off – Use arrowhead blocks set by DIMBLK
                    ' '' ''On – Use arrowhead blocks set by DIMBLK1 and DIMBLK2
                    ' '' ''acADim.Dimsah = 0

                    ' '' ''DIMBLK (R12) – Sets the arrowhead block displayed at the 
                    ' '' ''ends of dimension lines or leader lines. To return to the 
                    ' '' ''default, closed-filled arrowhead display, enter a single 
                    ' '' ''period (.). You can also enter the names of user-defined 
                    ' '' ''arrowhead blocks.
                    ' '' ''Standard blocks shown below. Note: 
                    ' '' ''Annotative blocks cannot be used as custom arrowheads
                    ' '' '' for dimensions or leaders.
                    ' '' ''“” = closed filled
                    ' '' ''“_DOT” = dot
                    ' '' ''“_DOTSMALL” = dot small
                    ' '' ''“_DOTBLANK”= dot blank
                    ' '' ''“_ORIGIN” = origin indicator
                    ' '' ''“_ORIGIN2″ = origin indicator 2
                    ' '' ''“_OPEN” = open
                    ' '' ''“_OPEN90″ = right angle
                    ' '' ''“_OPEN30″ = open 30
                    ' '' ''“_CLOSED” = closed
                    ' '' ''“_SMALL” = dot small blank
                    ' '' ''“_NONE” = none
                    ' '' ''“_OBLIQUE” = oblique
                    ' '' ''“_BOXFILLED” = box filled
                    ' '' ''“_BOXBLANK” = box
                    ' '' ''“_CLOSEDBLANK” = closed blank
                    ' '' ''“_DATUMFILLED” = datum triangle filled
                    ' '' ''“_DATUMBLANK” = datum triangle
                    ' '' ''“_INTEGRAL” = integral
                    ' '' ''“_ARCHTICK” = architectural tick
                    ' '' ''DIMBLK1 (R12) – Sets the arrowhead for the first end 
                    ' '' ''of the dimension line when DIMSAH is on. 
                    ' '' ''To return to the default, closed-filled 
                    ' '' ''arrowhead display, enter a single period (.).
                    ' '' ''DIMBLK2(R12) – Sets the arrowhead for the 
                    ' '' ''second end of the dimension line when DIMSAH is on. 
                    ' '' ''To return to the default, closed-filled arrowhead 
                    ' '' ''display, enter a single period (.). For a list of 
                    ' '' ''arrowhead entries, see DIMBLK.
                    ' '' ''acADim.Dimblk1 = ObjectId.Null
                    ' '' ''acADim.Dimblk2 = ObjectId.Null

                    ' '' ''DIMCLRD (R12) – Assigns colors to dimension lines, 
                    ' '' ''arrowheads, and dimension leader lines. Also controls 
                    ' '' ''the color of leader lines created with the LEADER command. 
                    ' '' ''Color numbers are displayed in the Select Color dialog box. 
                    ' '' ''For BYBLOCK, enter 0. For BYLAYER, enter 256.
                    ' '' '' acADim.Dimclrd = 

                    ' '' ''DIMCLRE (R12) – Assigns colors to dimension extension 
                    ' '' ''lines. Color numbers are displayed in the Select Color 
                    ' '' ''dialog box. For BYBLOCK, enter 0. For BYLAYER, enter 256.
                    ' '' '' acADim.Dimclre = 
                    ' '' ''DIMCLRT (R12) – Assigns colors to dimension 
                    ' '' ''text. The color can be any valid color number.
                    ' '' '' acADim.Dimclrt = 

                    ' '' ''DIMDEC (R12) – Sets the number of decimal 
                    ' '' ''places displayed for the primary units of a dimension. 
                    ' '' ''The precision is based on the units or angle 
                    ' '' ''format you have selected.
                    ' '' ''acADim.Dimdec = 2

                    ' '' ''0
                    ' '' ''Positions the text above the dimension line and center-justifies it between the extension lines
                    ' '' ''1
                    ' '' ''Positions the text next to the first extension line
                    ' '' ''2
                    ' '' ''Positions the text next to the second extension line
                    ' '' ''3
                    ' '' ''Positions the text above and aligned with the first extension line
                    ' '' ''4
                    ' '' ''Positions the text above and aligned with the second extension line
                    '' ''acADim.Dimjust = 0 '//horizontal justification for dimension text.

                    ' '' ''// the ratio between true value and displayied value
                    ' '' ''//acADim.Dimlfac = 0.5

                    '' ''Dim dAng As Double
                    '' ''Dim dAng1 As Double
                    '' ''Dim xTx As Double, yTx As Double
                    '' ''dAng1 = Math.Atan2( _
                    '' ''    lary.ln(i).N_2 - lary.ln(i).N_1, _
                    '' ''    lary.ln(i).E_2 - lary.ln(i).E_1)
                    '' ''dAng = dAng1 + Math.PI / 2
                    '' ''If (dAng > Math.PI * 2) Then dAng = dAng - Math.PI * 2
                    '' ''xTx = (lary.ln(i).E_2 + lary.ln(i).E_1) / 2
                    '' ''yTx = (lary.ln(i).N_2 + lary.ln(i).N_1) / 2
                    '' ''If (acADim.Measurement < (dTxtH * 2.5)) Then
                    '' ''    xTx = xTx + Math.Cos(dAng) * dTxtH * 2
                    '' ''    yTx = yTx + Math.Sin(dAng) * dTxtH * 2
                    '' ''    '0
                    '' ''    'Moves the dimension line with dimension text
                    '' ''    '1
                    '' ''    'Adds a leader when dimension text is moved
                    '' ''    '2
                    '' ''    'Allows text to be moved freely without a leader
                    '' ''    acADim.Dimtmove = 1 '//Specifies how dimension text is drawn when text is moved.
                    '' ''    acADim.TextRotation = 0.00001
                    '' ''Else
                    '' ''    xTx = xTx + Math.Cos(dAng) * dTxtH
                    '' ''    yTx = yTx + Math.Sin(dAng) * dTxtH
                    '' ''    '0
                    '' ''    'Moves the dimension line with dimension text
                    '' ''    '1
                    '' ''    'Adds a leader when dimension text is moved
                    '' ''    '2
                    '' ''    'Allows text to be moved freely without a leader
                    '' ''    acADim.Dimtmove = 2 '//Specifies how dimension text is drawn when text is moved.
                    '' ''End If
                    '' ''acADim.TextPosition = New Point3d( _
                    '' ''    xTx, _
                    '' ''    yTx, _
                    '' ''    0)

